/*
 * Copyright (c) 2018-2023 北京华恒盛世科技有限公司
 * QUICKPOOL is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *     http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
*/

#include <unistd.h>
#include <strings.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <errno.h>
#include <time.h>

#include "lib.h"
#include "echkpnt.lib.h"

static FILE  *m_pLogFile = NULL;
static char  *m_pMessageHeader = NULL;
static char  logMesgBuf[PATH_MAX+1];

char *
getEchkpntMethodDir(char *pChkpnt_Cmd, const char *pProgramName, const char *pMethodName)
{
    char  tmp_chkpnt_cmd[PATH_MAX+1];
    char *pChkpntBuf = NULL;

    if (pProgramName == NULL) {
        snprintf(logMesgBuf, PATH_MAX, "%s : parameter pProgramName is NULL\n", __func__);
        fprintf(stderr, "%s", logMesgBuf);
        logMesg(logMesgBuf);
        return NULL;
    }

    if (pChkpnt_Cmd == NULL) {
        pChkpntBuf = tmp_chkpnt_cmd;
    } else {
        pChkpntBuf = pChkpnt_Cmd;
    }

    if (gf_qp_init("echkpnt") < 0) {
        snprintf(logMesgBuf, PATH_MAX, "%s : gf_qp_init() failed\n", __func__);
        logMesg(logMesgBuf);
        return NULL;
    }

    if (baseParams[QP_CHKPNT_METHOD_DIR].string_value != NULL) {
        strncpy(pChkpntBuf, baseParams[QP_CHKPNT_METHOD_DIR].string_value, PATH_MAX);
    } else if (baseParams[BASE_SERVERDIR].string_value != NULL) {
        strncpy(pChkpntBuf, baseParams[BASE_SERVERDIR].string_value, PATH_MAX);
    }  else {
        snprintf(logMesgBuf, PATH_MAX, "%s : can't get the SERVERDIR value\n", __func__);
        fprintf(stderr,"%s",logMesgBuf);
        logMesg(logMesgBuf);
        return NULL;
    }

    strncat(pChkpntBuf, "/", PATH_MAX);
    strncat(pChkpntBuf, pProgramName, PATH_MAX);
    strncat(pChkpntBuf, ".", PATH_MAX);

    if (pMethodName != NULL) {
        strncat(pChkpntBuf, pMethodName, PATH_MAX);
    } else {
        strncat(pChkpntBuf,ECHKPNT_DEFAULT_METHOD, PATH_MAX);
    }

    if (access(pChkpntBuf, X_OK) < 0) {
        snprintf(logMesgBuf, PATH_MAX, "%s : the %s is not executed \n%s\n",
                 __func__, pChkpntBuf, errno ? strerror(errno) : "");
        fprintf(stderr,"%s",logMesgBuf);
        logMesg(logMesgBuf);
        return NULL;
    }

    if (pChkpnt_Cmd == NULL) {
        pChkpntBuf = copy_string(pChkpntBuf);
    }

    return(pChkpntBuf);
}

int  
getChkpntDirFile(char *pPathBuf, const char *pFileName)
{
    char *pChkpntPath = NULL;
    int iIndex;

    if (pPathBuf == NULL) {
        return -1;
    }
    strncpy(pPathBuf, "", PATH_MAX);

    pChkpntPath = getenv(ECHKPNT_CHKPNT_DIR);

    if (pChkpntPath != NULL) {
        if (NULL != strstr(pChkpntPath, "../")) {
            snprintf(logMesgBuf, PATH_MAX, "%s : QP_CHKPNT_DIR <%s> cannot have \"../\".\n",
                     __func__, pChkpntPath);
            logMesg(logMesgBuf);
            return -1;
        }

        snprintf(pPathBuf, PATH_MAX, "%s/", pChkpntPath);
    } else {
        snprintf(logMesgBuf, PATH_MAX, "%s : QP_CHKPNT_DIR is not defined\n", __func__);
        logMesg(logMesgBuf);
        return -1;
    }

    iIndex = strlen(pPathBuf);
    if (iIndex > 0) {
        while(pPathBuf[--iIndex] != '/');
        iIndex += 2;
        pPathBuf[iIndex] = '\0';
    }

    if (pFileName != NULL) {

        char tmpFileName[PATH_MAX+1];
        char *pFileNameChar = tmpFileName;
        strncpy(tmpFileName, pFileName, PATH_MAX);
        while(*(pFileNameChar) == '/') {
            pFileNameChar++;
        }

        strncat(pPathBuf, pFileNameChar, PATH_MAX);
    }
    return 0;
}

int 
initLog(char *pMesgHeader)
{
    char logFileName[PATH_MAX+1];

    if (m_pLogFile != NULL) {
        return 0;
    }

    if (getChkpntDirFile(logFileName, ECHKPNT_LOG_FILENAME) != 0) {
        return -1;
    }

    m_pLogFile = fopen(logFileName,"a");
    if (m_pLogFile == NULL) {
        return -1;
    }

    if (m_pMessageHeader != NULL) {
        free(m_pMessageHeader);
    }

    m_pMessageHeader = copy_string(pMesgHeader);
    fprintf(m_pLogFile,"########### begin to checkpoint ############\n");

    return 0;
}

void
closeLog(){
    if (m_pLogFile != NULL) {
        fprintf(m_pLogFile,"########### %s end checkpoint ###########\n\n",
                m_pMessageHeader != NULL? m_pMessageHeader : "");
        fclose(m_pLogFile);
        m_pLogFile = NULL;
    }
    if (m_pMessageHeader != NULL) {
        free(m_pMessageHeader);
    }

}

void
logMesg(const char *pMessage)
{
    if (NULL == m_pLogFile || NULL == pMessage || NULL == m_pMessageHeader) {
        return;
    }

    time_t tTime;
    tTime = time(NULL);
    if (tTime != (time_t)-1){
        int ii;
        char timebuf[TIMESTRINGLEN];

        ctime_2string(CTIME_FORMAT_a_b_d_T_Y, &tTime, timebuf);

        ii = strlen(timebuf);
        if (timebuf[ii -1] == '\n'){ 
            timebuf[ii - 1] = '\0';
        }

        fprintf(m_pLogFile,"%s : %s : %s", timebuf, m_pMessageHeader, pMessage);
        fflush(m_pLogFile);
    }	


    return;
}

